using System;
using System.Collections.Generic;
using System.Net;
using System.Net.NetworkInformation;

namespace Pscx.Commands.Net
{
    class PingExecutorSync : PingExecutor
    {
        public PingExecutorSync(PingHostCommand command)
            : base(command)
        {
        }

        internal override void Send(string hostOrAddress)
        {
            try
            {
                Send(Dns.GetHostEntry(hostOrAddress));
            }
            catch(Exception exc)
            {
                Command.WriteError(PscxErrorRecord.GetHostEntryError(hostOrAddress, exc));
            }
        }

        internal override void Send(IPAddress address)
        {
            try
            {
                Send(Dns.GetHostEntry(address));
            }
            catch(Exception exc)
            {
                Command.WriteError(PscxErrorRecord.GetHostEntryError(address.ToString(), exc));
            }
        }

        internal override void Send(IPHostEntry host)
        {
            new PingTaskSync(this, host).Send();
        }

        internal override void WriteInfo(PingHostInfo result)
        {
            result.WriteToPipeline(Command);
            Statistics.Add(result);
        }

        internal override void WriteStatistics(PingTaskBase task)
        {
            Statistics[task.HostEntry].WriteToHost(Command);
        }

        public override void Dispose()
        {
        }
    }

    class PingTaskSync : PingTaskBase
    {
        public PingTaskSync(PingExecutor exec, IPHostEntry host)
            : base(exec, host)
        {
        }

        public void Send()
        {
            using (Ping ping = new Ping())
            {
                foreach (IPAddress ip in Addresses)
                {
                    for (int i = 0; i < Count; i++)
                    {
                        if (Executor.Command.Stopping)
                            return;

                        PingReply reply = null;
                        Exception error = null;

                        try
                        {
                            reply = ping.Send(ip, Timeout, Buffer, PingOptions);
                        }
                        catch (Exception exc)
                        {
                            error = exc;
                        }

                        PingHostInfo info = new PingHostInfo(HostEntry, reply, error, Buffer.Length);
                        Executor.WriteInfo(info);
                    }
                }
            }

            Executor.WriteStatistics(this);
        }
    }
}
